home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / benchmarks / mpping / mpping.c < prev   
Encoding:
C/C++ Source or Header  |  1991-07-31  |  6.4 KB  |  284 lines

  1. /* 
  2.  * mpping --
  3.  *
  4.  *    A multi-processor test program where a bunch of processes
  5.  *    pass a token between themselves in a ring-like fashion.
  6.  *    Command-line syntax:
  7.  *
  8.  *    mpping numProcs loopCount
  9.  *
  10.  *    "numProcs" is the number of processes to use (anything >= 1,
  11.  *    defaults to 4).  "loopCount" is the number of iterations to
  12.  *    run between time printouts (defaults to 1000).
  13.  *
  14.  * Copyright 1988 Regents of the University of California
  15.  * Permission to use, copy, modify, and distribute this
  16.  * software and its documentation for any purpose and without
  17.  * fee is hereby granted, provided that the above copyright
  18.  * notice appear in all copies.  The University of California
  19.  * makes no representations about the suitability of this
  20.  * software for any purpose.  It is provided "as is" without
  21.  * express or implied warranty.
  22.  */
  23.  
  24. #ifndef lint
  25. static char rcsid[] = "$Header: proto.c,v 1.2 88/03/11 08:39:08 ouster Exp $ SPRITE (Berkeley)";
  26. #endif not lint
  27.  
  28. #include <errno.h>
  29. #include <stdio.h>
  30. #include <proc.h>
  31. #include <signal.h>
  32. #include <status.h>
  33. #include <string.h>
  34. #include <sys/time.h>
  35.  
  36. /*
  37.  * The data structure below represents the ring around which the token
  38.  * gets passed.  The token gets passed by each process setting the
  39.  * "myTurn" field for the next process.
  40.  */
  41.  
  42. typedef struct {
  43.     int pid;        /* Identifier of this process. */
  44.     int myTurn;        /* Non-zero means previous process in ring has
  45.              * signalled this process;  this process must
  46.              * wait until this becomes non-zero. */
  47.     int signalMe;    /* Non-zero means that this process got tired
  48.              * of spinning on myTurn and went to sleep.  The
  49.              * predecessor process should wake it up with a
  50.              * SIGUSR1. */
  51.     int pad[5];        /* Fill out cache line so that each process's
  52.              * entry is in a different line. */
  53. } Process;
  54.  
  55. #define MAX_PROCESSES 100
  56.  
  57. volatile Process procs[MAX_PROCESSES];
  58. int numProcs = 4;
  59.  
  60. int numToTime = 1000;    /* Number of iterations to time at once. */
  61.  
  62. /*
  63.  * Forward declarations for procedures defined in this file:
  64.  */
  65.  
  66. extern void Ping();
  67. extern int SigUsr1();
  68.  
  69. /*
  70.  *----------------------------------------------------------------------
  71.  *
  72.  * main --
  73.  *
  74.  *    Main procedure:  fork off children.
  75.  *
  76.  * Results:
  77.  *    None.
  78.  *
  79.  * Side effects:
  80.  *    Creates children, which do the pinging.
  81.  *
  82.  *----------------------------------------------------------------------
  83.  */
  84.  
  85. main(argc, argv)
  86.     int argc;
  87.     char **argv;
  88. {
  89.     int i, myIndex;
  90.     ReturnStatus status;
  91.     struct timeval start, stop;
  92.     struct timezone tz;
  93.     int micros;
  94.     double timePer;
  95.     static struct sigvec vec = {SigUsr1, 0, 0};
  96.  
  97.     if (argc > 1) {
  98.     numProcs = atoi(argv[1]);
  99.     if ((numProcs <= 0) || (numProcs > MAX_PROCESSES)) {
  100.         fprintf(stderr, "Number of processes must be between %d and %d.\n",
  101.             1, MAX_PROCESSES);
  102.         exit(1);
  103.     }
  104.     }
  105.     if (argc > 2) {
  106.     numToTime = atoi(argv[2]);
  107.     if (numToTime <= 0) {
  108.         fprintf(stderr, "Loop count must be greater than zero.\n");
  109.         exit(1);
  110.     }
  111.     }
  112.     if (argc > 3) {
  113.     fprintf(stderr, "Usage: %s [numProcs [loopCount]]\n", argv[0]);
  114.     exit(1);
  115.     }
  116.  
  117.     /*
  118.      * Fork off child processes and initialize ping array.
  119.      */
  120.  
  121.     for (i = numProcs-1; i > 0; i--) {
  122.     procs[i].myTurn = procs[i].signalMe = 0;
  123.     status = Proc_Fork(1, &procs[i].pid);
  124.     if (status == PROC_CHILD_PROC) {
  125.         myIndex = i;
  126.         goto mainLoop;
  127.     }
  128.     if (status != SUCCESS) {
  129.         fprintf(stderr, "Error 0x%x in forking.", status);
  130.         goto killProcs;
  131.     }
  132.     }
  133.     myIndex = 0;
  134.     procs[0].pid = getpid();
  135.     procs[0].myTurn = 1;
  136.     procs[0].signalMe = 0;
  137.  
  138.     /*
  139.      * Main loop:  ping continually.  Process 0 times the execution
  140.      * and prints out the times.
  141.      */
  142.  
  143.     mainLoop:
  144.     if (sigvec(SIGUSR1, &vec, (struct sigvec *) NULL) != 0) {
  145.     fprintf(stderr, "Could enable signal handler: %s\n",
  146.         strerror(errno));
  147.     goto killProcs;
  148.     }
  149.     sigblock(sigmask(SIGUSR1));
  150.     i = 1;
  151.     if (myIndex == 0) {
  152.     gettimeofday(&start, &tz);
  153.     }
  154.     while (1) {
  155.     Ping(myIndex);
  156.     if ((myIndex == 0) && (i >= numToTime)) {
  157.         i = 1;
  158.         gettimeofday(&stop, &tz);
  159.         micros = (stop.tv_sec - start.tv_sec)*1000000
  160.             + (stop.tv_usec - start.tv_usec);
  161.         timePer = micros;
  162.         printf("Time per iteration: %.2f microseconds\n",
  163.             timePer/numToTime);
  164.         start = stop;
  165.     } else {
  166.         i += 1;
  167.     }
  168.     }
  169.  
  170.     /*
  171.      * Desperation:  if there's a major problem, come here to kill off
  172.      * all of the processes.
  173.      */
  174.  
  175.     killProcs:
  176.     procs[myIndex].pid = 0;
  177.     for (i = 0; i < numProcs; i++) {
  178.     if (procs[i].pid != 0) {
  179.         kill(procs[i].pid, SIGTERM);
  180.     }
  181.     }
  182.     exit(1);
  183. }
  184.  
  185. /*
  186.  *----------------------------------------------------------------------
  187.  *
  188.  * Ping --
  189.  *
  190.  *    Wait for this process to be pinged once, then ping the next
  191.  *    process in the chain.
  192.  *
  193.  * Results:
  194.  *    None.
  195.  *
  196.  * Side effects:
  197.  *    This process gets delayed, and the next process get woken up.
  198.  *
  199.  *----------------------------------------------------------------------
  200.  */
  201.  
  202. void
  203. Ping(index)
  204.     int index;        /* Index of this process in the table "procs". */
  205. {
  206.     register Process *p;
  207.     int i;
  208. #ifdef DEBUG
  209.     char msg[200];
  210. #endif
  211.  
  212.     p = &procs[index];
  213.  
  214.     /*
  215.      * Wait for a while to get pinged.  If nothing happens, then go to
  216.      * sleep until re-awoken.
  217.      */
  218.  
  219.     while (1) {
  220.     for (i = 0; i < 200; i++) {
  221.         if (p->myTurn) {
  222.         goto pinged;
  223.         }
  224.     }
  225.     p->signalMe = 1;
  226.     if (!p->myTurn) {
  227. #ifdef DEBUG
  228.         sprintf(msg, "Process %d (%x) going to sleep.\n", index, p->pid);
  229.         write(1, msg, strlen(msg));
  230. #endif
  231.         sigpause(0);
  232.     }
  233.     }
  234.  
  235.     /*
  236.      * We got the token.  Now give it to the next process.  Wake the
  237.      * process up if it went to sleep.
  238.      */
  239.  
  240.     pinged:
  241. #ifdef DEBUG
  242.     sprintf(msg, "Process %d (%x) got token.\n", index, p->pid);
  243.     write(1, msg, strlen(msg));
  244. #endif
  245.     p->myTurn = 0;
  246.     index += 1;
  247.     if (index >= numProcs) {
  248.     index = 0;
  249.     }
  250.     p = &procs[index];
  251.     p->myTurn = 1;
  252.     if (p->signalMe) {
  253. #ifdef DEBUG
  254.     sprintf(msg, "Waking up process %d (%x).\n", index, p->pid);
  255.     write(1, msg, strlen(msg));
  256. #endif
  257.     p->signalMe = 0;
  258.     kill(p->pid, SIGUSR1);
  259.     }
  260. }
  261.  
  262. /*
  263.  *----------------------------------------------------------------------
  264.  *
  265.  * SigUsr1 --
  266.  *
  267.  *    This is the interrupt handler for SIGUSR1 signals.  It doesn't
  268.  *    do anything (all that matters is that we got the signal).
  269.  *
  270.  * Results:
  271.  *    None.
  272.  *
  273.  * Side effects:
  274.  *    None.
  275.  *
  276.  *----------------------------------------------------------------------
  277.  */
  278.  
  279. int
  280. SigUsr1()
  281. {
  282.     return 0;
  283. }
  284.